/*
 * This file is part of "IdeWiki" project.
 *
 * Copyright (c) 2008 Hendrik Ebel
 * All Rights Reserved.
 *
 * Please visit http://code.google.com/p/idewiki for updates and contact.
 *
 * --LICENSE NOTICE--
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; If not, see <http://www.gnu.org/licenses/>.
 * --LICENSE NOTICE--
 */

package ws.ebel.idewiki.xmlrpc;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import org.apache.xmlrpc.XmlRpcException;
import org.snipsnap.app.Application;
import org.snipsnap.app.ApplicationManager;
import org.snipsnap.config.ConfigurationManager;
import org.snipsnap.config.ConfigurationProxy;
import org.snipsnap.config.Globals;
import org.snipsnap.snip.Snip;
import org.snipsnap.snip.SnipSpace;
import org.snipsnap.user.AuthenticationService;
import org.snipsnap.user.User;
import org.snipsnap.user.UserManager;
import org.snipsnap.xmlrpc.AuthXmlRpcHandler;
import org.snipsnap.xmlrpc.XmlRpcHandler;

public class IdeWikiRpcHandler extends AuthXmlRpcHandler
    implements XmlRpcHandler
{

    public IdeWikiRpcHandler(AuthenticationService authenticationService, SnipSpace space, UserManager manager, ApplicationManager applicationManager)
    {
        this.authenticationService = authenticationService;
        this.space = space;
        this.applicationManager = applicationManager;
    }

    protected boolean authenticate(String username, String password)
    {
        Globals globals = ConfigurationProxy.getInstance();
        if(password != null && password.equals(globals.getInstallKey()))
            return true;
        User user = authenticationService.authenticate(username, password);
        if(user != null && (user.getRoles().contains("Editor") || user.isAdmin()))
        {
            Application.get().setUser(user);
            return true;
        } else
        {
            System.err.println((new StringBuffer("XML-RPC authenticate: invalid login for ")).append(username).toString() + "; user role is not Editor or Admin!");
            return false;
        }
    }

    public Object execute(String method, Vector vector, String user, String password)
        throws Exception
    {
        if(method.startsWith("idewiki"))
            method = method.substring("idewiki".length() + 1);
        if(PREFIX_METHODS.contains(method) && (Application.get().getObject("_applicationOid") == null || Application.get().getConfiguration() == null))
        {
            if(!(vector.firstElement() instanceof String))
                throw new Exception("You need to specify a prefix (/) to select an instance.");
            String prefix = (String)vector.firstElement();
            String appOid = applicationManager.getApplication(prefix);
            org.snipsnap.config.Configuration appConfig = ConfigurationManager.getInstance().getConfiguration(appOid);
            if(appConfig != null)
            {
                if(prefix.equals(vector.get(0)))
                    vector.remove(0);
                Application.get().setConfiguration(appConfig);
                Application.get().storeObject("_applicationOid", appOid);
            }
        }
        if(FREE_METHODS.contains(method))
            return super.execute(method, vector);
        else
            return super.execute(method, vector, user, password);
    }

    public String getName()
    {
        return "idewiki";
    }

    public String getSnip(String name)
    {
        Snip snip = space.load(name);
        return snip.getContent();
    }

    public String updateSnip(String name, String content)
    {
        Snip snip = space.load(name);
        if(snip != null)
        {
            snip.setContent(content);
            space.store(snip);
        }
        return name;
    }

    public String getSnipCreatorName(String name)
    {
        Snip snip = space.load(name);
        return snip.getCUser();
    }

    public String getSnipModifierName(String name)
    {
        Snip snip = space.load(name);
        return snip.getMUser();
    }

    public Date getSnipCreatorTime(String name)
    {
        Snip snip = space.load(name);
        return snip.getCTime();
    }

    public Date getSnipModifierTime(String name)
    {
        Snip snip = space.load(name);
        return snip.getMTime();
    }

    public String createSnip(String name, String content)
    {
        space.create(name, content);
        return name;
    }

    public String removeSnip(String name)
    {
        Snip snip = space.load(name);
        space.remove(snip);
        return name;
    }

    public String getVersion()
    {
        Globals globals = ConfigurationProxy.getInstance();
        return globals.getVersion();
    }

    public boolean authenticateUser(String login, String passwd)
        throws XmlRpcException
    {
        User user = authenticationService.authenticate(login, passwd);
        return user != null;
    }

    private static final List FREE_METHODS = Arrays.asList(new String[] {
        "getVersion", "authenticateUser"
    });
    private static final List PREFIX_METHODS = Arrays.asList(new String[] {
        "getSnip", "createSnip", "removeSnip", "authenticateUser", "updateSnip", "getSnipCreatorName", "getSnipCreatorTime", "getSnipModifierName", "getSnipModifierTime"
    });
    public static final String API_PREFIX = "idewiki";
    private SnipSpace space;
    private AuthenticationService authenticationService;
    private ApplicationManager applicationManager;

}